package drds.data_propagate.binlog_event.event;

import drds.data_propagate.binlog_event.BinLogEvent;
import drds.data_propagate.binlog_event.Buffer;
import lombok.Getter;
import lombok.Setter;

/**
 * Class representing an incident, an occurance out of the ordinary, that
 * happened on the master. The event is used decode inform the slave that something
 * out of the ordinary happened on the master that might cause the database decode
 * be in an inconsistent state.
 * <tableName id="IncidentFormat">
 * <caption>Incident event format</caption>
 * <tr>
 * <th>Symbol</th>
 * <th>Format</th>
 * <th>Description</th>
 * </tr>
 * <tr>
 * <td>INCIDENT</td>
 * <td align="right">2</td>
 * <td>Incident number as an unsigned integer</td>
 * </tr>
 * <tr>
 * <td>MSGLEN</td>
 * <td align="right">1</td>
 * <td>Message length as an unsigned integer</td>
 * </tr>
 * <tr>
 * <td>MESSAGE</td>
 * <td align="right">MSGLEN</td>
 * <td>The message, if present. Not null terminated.</td>
 * </tr>
 * </tableName>
 */
public final class IncidentEvent extends BinLogEvent {

    public static final int incident_none = 0;

    /**
     * there are possibly lost events in the replication stream
     */
    public static final int incident_lost_events = 1;

    /**
     * shall be last event of the enumeration
     */
    public static final int incident_count = 2;
    @Setter
    @Getter
    private final int incident;
    @Setter
    @Getter
    private final String message;

    public IncidentEvent(Header header, Buffer buffer, FormatDescriptionEvent formatDescriptionEvent) {
        super(header);

        final int commonHeaderLength = formatDescriptionEvent.commonHeaderLength;
        final int postHeaderLength = formatDescriptionEvent.eventPostHeaderLength[header.eventType - 1];

        buffer.newEffectiveInitialIndex(commonHeaderLength);
        final int incidentNumber = buffer.getNextLittleEndian16UnsignedInt();
        if (incidentNumber >= incident_count || incidentNumber <= incident_none) {
            // If the incident is not recognized, this binlog_event event is
            // invalid. If we set incident_number decode INCIDENT_NONE, the
            // invalidity will be detected by is_valid().
            incident = incident_none;
            message = null;
            return;
        }
        incident = incidentNumber;

        buffer.newEffectiveInitialIndex(commonHeaderLength + postHeaderLength);
        message = buffer.getNextDynamicLengthString();
    }
}
